package poker;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;

/**
 * The methods for analyzing winning hands.
 *
 * Following rules apply to all the methods in this class:
 * The object h representing hand:
 * 1. must not be null.
 * 2. must contain exactly five Cards.
 *
 * @author Antti M. Harittu
 */
public class Hands {
    private static ArrayList<Integer> l;
    private static int a;
    private static int b;
    private static int c;
    private static int d;
    private static int e;

    /**
     * This method returns a sorted list that contains the ranks of the hand.
     *
     * @param h
     * @return
     */
    public static ArrayList<Integer> returnSorted(LinkedList<Card> h) {
        ArrayList<Integer> l = new ArrayList<Integer>();
        for (int i = 0; i < 5; i++) {
            l.add(h.get(i).getR());
        }
        Collections.sort(l);
        return l;
    } // end returnSorted

    /**
     * This method returns the value of the highest rank of the cards in the
     * hand.
     *
     * @param h
     * @return
     */
    public static int max(LinkedList<Card> h) {
        int x = 2;
        for (int i = 0; i < 5; i++) {
            int t = h.get(i).getR();
            if (t > x) {
                x = t;
            }
        }
        return x;
    } // end max   

    /**
     * This method returns the rank of a pair. If the hand does not contain a
     * pair, number 0 is returned.
     *
     * @param h
     * @return
     */
    public static int pair(LinkedList<Card> h) {
        if (a == b) { return a; } // OO---
        if (b == c) { return b; } // -OO--
        if (c == d) { return c; } // --OO-   
        if (d == e) { return d; } // ---OO
        return 0;
    } // end pair

    /**
     * This method returns the highest rank of two pairs. If the hand does not
     * contain two pairs or a combination of a four of a kind, number 0 is
     * returned.
     *
     * @param h
     * @return
     */
    public static int twoPairs(LinkedList<Card> h) {
        // OOoo-
        if (a == b && c == d) {
            if (a > c) {
                return a;
            } else {
                return c;
            }
        }
        // OO-oo
        if (a == b && d == e) {
            if (a > d) {
                return a;
            } else {
                return d;
            }
        }
        // -OOoo
        if (b == c && d == e) {
            if (b > d) {
                return a;
            } else {
                return d;
            }
        }
        return 0;
    } // end twoPairs

    /**
     * This method returns the highest rank of a three of a kind. If the hand
     * doesn't contain a combination of a three of a kind, number 0 is returned.
     *
     * @param h
     * @return
     */
    public static int threeOfAKind(LinkedList<Card> h) {
        if (a == b && b == c) { return a; } // OOO--
        if (b == c && c == d) { return b; } // -OOO-
        if (c == d && d == e) { return c; } // --OOO
        return 0;
    } // threeOfAKind

    /**
     * This method returns the highest rank of a fullhouse. If the hand does not
     * contain fullhouse, number 0 is returned.
     *
     * @param h
     * @return
     */
    public static int fullhouse(LinkedList<Card> h) {
        int three = threeOfAKind(h);
        int pair = pair(h);
        if (three != 0
                && pair != 0
                && three != pair
                && three > 0
                && pair > 0) {
            if (three > pair) {
                return three;
            } else {
                return pair;
            }
        }
        return 0;
    } // fullhouse

    /**
     * This method returns the highest rank of a four of a kind. If the hand
     * does not contain a four of a kind, number 0 is returned.
     *
     * @param h
     * @return
     */
    public static int fourOfAKind(LinkedList<Card> h) {
        if (a == b && b == c && c == d) { return a; } // OOOO-
        if (b == c && c == d && d == e) { return b; } // -OOOO
        return 0;
    } // fourOfAKind

    /**
     * This method returns the highest rank of a straight. If the hand does not
     * contain a combination of a straight, number 0 is returned.
     *
     * @param h
     * @return
     */
    public static int straight(LinkedList<Card> h) {
        if ((a + 1) == b && (b + 1) == c && (c + 1) == d && (d + 1) == e) {
            return e;
        }
        return 0;
    } // end straight

    /**
     * This method returns the highest rank of a straight flush. If the hand
     * does not contain a straight flush, number 0 is returned.
     *
     * @param h
     * @return
     */
    public static int straightFlush(LinkedList<Card> h) {
        // Suits
        boolean b = true;
        char v = h.get(0).getS();
        for (int i = 1; i < 5; i++) {
            if (v != h.get(i).getS()) {
                b = false;
            }
        }
        // Ranks
        if (b) { return straight(h); }
        return 0;
    } // end straightFlush

    /**
     * This method communicates with the main program returning a vector that
     * contains the code of the winning hand and the value of the highest rank
     * of the hand.
     * 
     * @param h
     * @return {hand, rank}
     */
    public static int[] winningHand(LinkedList<Card> h) {
        l = returnSorted(h);
        a = l.get(0);
        b = l.get(1);
        c = l.get(2);
        d = l.get(3);
        e = l.get(4);

        int t; // temp
        
        t = straightFlush(h); if (t > 0) { return new int[]{0, t}; }

        t = straight(h); if (t > 0) { return new int[]{1, t}; }

        t = fourOfAKind(h); if (t > 0) { return new int[]{2, t}; }

        t = fullhouse(h); if (t > 0) { return new int[]{3, t}; }

        t = threeOfAKind(h); if (t > 0) { return new int[]{4, t}; }

        t = twoPairs(h); if (t > 0) { return new int[]{5, t}; }

        t = pair(h); if (t > 0) { return new int[]{6, t}; }

        return new int[]{7, max(h)};
    } // end winningHand
} // end class Hands